/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tpdisenio2009.mvp.presenter;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Date;
import java.util.List;
import tpdisenio2009.model.beans.FantasyTeam;
import tpdisenio2009.model.beans.FantasyTeamPlayer;
import tpdisenio2009.model.beans.FantasyTeamScoreByTournamentDate;
import tpdisenio2009.model.beans.Score;
import tpdisenio2009.model.beans.SoccerMatch;
import tpdisenio2009.model.beans.SoccerPlayer;
import tpdisenio2009.model.beans.TournamentDate;
import tpdisenio2009.mvp.display.CloseTournamentDateView;
import tpdisenio2009.services.FantasyTeamPlayerService;
import tpdisenio2009.services.FantasyTeamScoreByTournamentDateService;
import tpdisenio2009.services.FantasyTeamService;
import tpdisenio2009.services.ScoreService;
import tpdisenio2009.services.SoccerMatchService;
import tpdisenio2009.services.TournamentDateService;

/**
 *
 * @author DeuterioX
 */
public class CloseTournamentDatePresenter extends DefaultPresenter<CloseTournamentDateView>{

    public ItemListener dateChange;

    public ActionListener closeDate;

    private final SoccerMatchService smService;

    private final TournamentDateService tdService;

    private final FantasyTeamService ftService;

    private final FantasyTeamPlayerService ftpService;

    private final ScoreService sService;

    private final FantasyTeamScoreByTournamentDateService ftstdService;

    public CloseTournamentDatePresenter( CloseTournamentDateView view ) {
        super( view );

        smService = new SoccerMatchService();
        tdService = new TournamentDateService();
        ftService = new FantasyTeamService();
        ftpService = new FantasyTeamPlayerService();
        sService = new ScoreService();
        ftstdService = new FantasyTeamScoreByTournamentDateService();
        getView().setDates( tdService.getDates() );
        getView().setState( smService.getMatchState() );
        getView().setFirstOpenDate( tdService.getFirstOpenTournamentDate() );
        getView().loadMatches( smService.getSoccerMatchByTournamentDate( tdService.getFirstOpenTournamentDate() ) );

        bind();
    };

    private boolean isAllMatchesClose( List<SoccerMatch> matches ) {

        for ( SoccerMatch match : matches ) {
            if ( match.getState().equals( SoccerMatch.POSTPONED_MATCH ) ) {
                return false;
            }
        }
        return true;
    }

    private boolean isAnyMatchPending( List<SoccerMatch> matches ) {

        for ( SoccerMatch match : matches ) {
            if ( match.getState().equals( SoccerMatch.NON_PLAYED_MATCH ) ) {
                return true;
            }
        }
        return false;
    }

    public void bind() {

        dateChange = new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                getView().loadMatches( smService.getSoccerMatchByTournamentDate( getView().getDate() ) );
            }
        };
        getView().addDateChangeListener( dateChange );
        closeDate = new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                if( showConfirmation( "<html>¿Confirma que desea cerrar la fecha <strong>" + getView().getDate().toString() + "</strong>?" ) ) {

                    if ( getView().getDate().getBanDate() == null) {
                        getView().showError( "<html>La fecha (<strong>" + getView().getDate().toString() + "</strong>) que desea cerrar no tiene definida un periodo de veda.</html>",
                                "Error: al cerrar fecha");
                    } else if ( getView().getDate().getInitialDate().after( new Date() ) ) {
                        getView().showError( "<html>La fecha de inicio de la fecha (<strong>" + getView().getDate().toString() + "</strong>) es superior a la fecha actual.</html>",
                                "Error: al cerrar fecha");
                    } else if ( getView().getDate().getBanDate().after( new Date() ) ) {
                        getView().showError( "<html>La fecha de veda de la fecha (<strong>" + getView().getDate().toString() + "</strong>) es superior a la fecha actual.</html>",
                                "Error: al cerrar fecha");
                    } else if ( getView().getDate().getState().equals( TournamentDate.CLOSED_DATE ) ) {
                        getView().showError( "<html>La fecha que desea cerrar (<strong>" + getView().getDate().toString() + "</strong>) ya se encuentra cerrada.</html>",
                                "Error: fecha cerrada");
                    } else if ( !getView().getDate().equals( tdService.getFirstOpenTournamentDate() ) ) {
                        getView().showError( "<html>Existen fechas previas abiertas anterior a la fecha (<strong>" + getView().getDate().toString() + "</strong>) que deben cerrarse primero.</html>",
                                "Error: al cerrar fecha");
                    } else if ( !isAllMatchesClose( getView().getSoccerMatch() ) ) {
                        getView().showError( "<html>Existen partidos pospuestos que todavía no se han jugado<br>" +
                                "Por favor, espere a que todos los partidos se hayan jugado para" +
                                " cerrar la fecha.",
                                "Error: al cerrar fecha");
                    } else if ( isAnyMatchPending( getView().getSoccerMatch() ) ) {
                        getView().showError( "<html>Existen jugadores de la fecha a los que no se le han<br>" +
                                "asiganado puntos todavía. Por favor, espere a que <br>todos los " +
                                "jugadores tengan los puntos asignados.</html>",
                                "Error: al cerrar fecha");
                    } else {
                        //como no se puede dar de baja un fantasyTeam, obtengo todos y actualizo todos.
                        List<FantasyTeam> teams = ftService.getAllFantasyTeam();
                        TournamentDate date = getView().getDate();
                        for ( FantasyTeam team : teams ) {

                            Integer teamScoreForDate = getTotalScoreByTeam( team, date);
                            /*
                            List<Score> scores = sService.getScoresByTeamAndDate( team, date );
                            Integer teamScoreForDate = 0;
                            for ( Score score : scores ) {
                                teamScoreForDate += sService.getTotalScore( score.getId() );
                            } */

                            FantasyTeamScoreByTournamentDate ftstd = new FantasyTeamScoreByTournamentDate();
                            ftstd.setFantasyTeam( team );
                            ftstd.setScore( teamScoreForDate );
                            ftstd.setTournamentDate( date );
                            ftService.updateFantasyTeamScore( team.getId(), teamScoreForDate );
                            ftstdService.createFantasyTeamScoreByTournamentDate( ftstd );
                        }
                        TournamentDate closedDate = date;
                        closedDate.setState( TournamentDate.CLOSED_DATE );
                        tdService.update( closedDate );
                        getView().showNotification("<html>Felicitaciones, la fecha se ha cerrado satisfactoriamente.<br>Recuerde que debe abrir la próxima fecha.</html>", "Cierre exitoso");
                    }
                }
            };
        };
        getView().addCloseDateListener( closeDate );
    };

    public void unbind() {

        if ( closeDate != null)
            getView().removeCloseDateListener( closeDate );
        if ( dateChange != null)
            getView().removeDateChangeListener( dateChange );
    }

    private Integer getTotalScoreByTeam( FantasyTeam team, TournamentDate date ) {

        List<Score> scores = sService.getScoresByTeamAndDate( team, date );
        List<FantasyTeamPlayer> players = ftpService.getFantasyTeamPlayersByDate(team, date);

        Integer teamScoreForDate = 0;
        int gk = 0, df = 0, mf = 0, fw = 0;

        for ( Score score : scores ) {
            for ( FantasyTeamPlayer player : players ) {
                if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && score.getSoccerPlayer().getPosition().equals(SoccerPlayer.GOALKEEPER_POSITION) && player.getRol().equals(FantasyTeamPlayer.TITULAR_ROLE) ) {
                    gk++;
                    break;
                } else if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && score.getSoccerPlayer().getPosition().equals(SoccerPlayer.DEFENDER_POSITION) && player.getRol().equals(FantasyTeamPlayer.TITULAR_ROLE) ) {
                    df++;
                    break;
                } else if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && score.getSoccerPlayer().getPosition().equals(SoccerPlayer.MIDFIELDER_POSITION) && player.getRol().equals(FantasyTeamPlayer.TITULAR_ROLE) ) {
                    mf++;
                    break;
                } else if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && score.getSoccerPlayer().getPosition().equals(SoccerPlayer.FORWARD_POSITION) && player.getRol().equals(FantasyTeamPlayer.TITULAR_ROLE) ) {
                    fw++;
                    break;
                }
            }
        }       

        if ( team.getCreationDate().before( date.getBanDate() ) ) {
            for ( Score score : scores ) {
                for ( FantasyTeamPlayer player : players ) {
                    if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && player.getRol().equals(FantasyTeamPlayer.TITULAR_ROLE) ) {
                        teamScoreForDate += sService.getTotalScore( score.getId() );                        
                    } else {
                        if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && gk == 0 && player.getRol().equals(FantasyTeamPlayer.SUBSTITUTE_ROLE) && player.getSoccerPlayer().getPosition().equals(SoccerPlayer.GOALKEEPER_POSITION) ) {
                            teamScoreForDate += sService.getTotalScore( score.getId() );                            
                        } else if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && df <= 3 && player.getRol().equals(FantasyTeamPlayer.SUBSTITUTE_ROLE) && player.getSoccerPlayer().getPosition().equals(SoccerPlayer.DEFENDER_POSITION) ) {
                            teamScoreForDate += sService.getTotalScore( score.getId() );                            
                        } else if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && mf < 3 && player.getRol().equals(FantasyTeamPlayer.SUBSTITUTE_ROLE) && player.getSoccerPlayer().getPosition().equals(SoccerPlayer.MIDFIELDER_POSITION) ) {
                            teamScoreForDate += sService.getTotalScore( score.getId() );                            
                        } else if ( score.getSoccerPlayer().equals(player.getSoccerPlayer()) && fw < 3 && player.getRol().equals(FantasyTeamPlayer.SUBSTITUTE_ROLE) && player.getSoccerPlayer().getPosition().equals(SoccerPlayer.FORWARD_POSITION) ) {
                            teamScoreForDate += sService.getTotalScore( score.getId() );                            
                        } else {
                            teamScoreForDate += 0;                            
                        }
                    }
                }
            }
        }
        return teamScoreForDate;
    }

    private boolean showConfirmation(String message) {
        return getView().showConfirmation( message );
    }
}
